package com.olap.starter.common.util;

import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.olap.starter.common.vo.BatchSaveParameter;
import com.olap.starter.pojo.TableDelete;
import com.olap.starter.util.IdUtil;

import java.util.*;

import static com.olap.starter.util.StringUtils.isNotEmpty;

/**
 * @author WBG
 * @date 2022/12/5 10:41
 * @describe
 */
public class OnlineUtils {

    public static Map<String, Object> getFiledMap(List<TableDelete> tableDeletes, boolean putValue) {
        Map<String, Object> filedMap = new HashMap<>();
        for (TableDelete tableDelete : tableDeletes) {
            filedMap.putAll(parseWhereToMap(tableDelete, putValue));
        }
        return filedMap;
    }

    public static boolean isNumeric(String str) {
        return str != null && str.matches("-?\\d+(\\.\\d+)?");
    }

    public static Object[] getDeleteSql(String tableName, Map<String, Object> filedMap, boolean delete) {
        StringBuilder sb = new StringBuilder();
        if (delete) {
            sb.append("DELETE FROM ");
            sb.append(tableName);
        } else {
            sb.append("UPDATE ");
            sb.append(tableName);
            sb.append(" SET deleted = 1 ");
        }
        sb.append(" WHERE ");
        Object[] values = new Object[filedMap.size()];
        boolean find = true;
        int i = 0;
        for (String filed : filedMap.keySet()) {
            if (isNumeric(filed)) {
                throw new RuntimeException("非法删除操作，字段非法！");
            }
            if (!find) {
                sb.append(" AND ");
            } else {
                find = false;
            }
            sb.append(filed).append(" = ?");
            values[i] = filedMap.get(filed);
            if (values[i] instanceof Long) {
                values[i] = ((Long) values[i]).longValue();
            }
            i++;
        }
        if (find) {
            throw new RuntimeException("非法删除操作，无参数！");
        }
        return new Object[]{sb.toString(), values};
    }

    public static String getDeleteSql(TableDelete tableDelete, Map<String, Object> filedMap, boolean delete) {
        StringBuilder sb = new StringBuilder();
        if (delete) {
            sb.append("DELETE FROM ");
            sb.append(tableDelete.getTableName());
        } else {
            sb.append("UPDATE ");
            sb.append(tableDelete.getTableName());
            sb.append(" SET deleted = 1 ");
        }
        sb.append(" WHERE ");
        boolean find = true;
        for (String filed : filedMap.keySet()) {
            if (!find) {
                sb.append(" AND ");
            } else {
                find = false;
            }
            if (tableDelete.getTheme() != null && tableDelete.getTheme().equals(filed.substring(0, 2))) {
                sb.append(filed.substring(3));
            } else {
                sb.append(filed);
            }
            sb.append(" = ?");
        }
        if (find) {
            throw new RuntimeException("删除SQL异常,没有携带必须参数！");
        }
        return sb.toString();
    }

    public static Map<String, Object> parseWhereToMap(TableDelete tableDelete, boolean putValue) {
        String[] filed = tableDelete.getWheres().replaceAll(" ", "").split(",");
        Map<String, Object> params = new HashMap<>();
        for (String f : filed) {
            String[] kv = f.split("=");

            if (kv.length == 1) {
                if (putValue) {
                    params.put(kv[0], kv[0]);
                } else {
                    params.put(kv[0], "");
                }
            } else if (kv.length == 2) {
                String fv = kv[1];
                if (fv.indexOf("${") == 0 && fv.lastIndexOf("}") == fv.length() - 1) {
                    //如果是true  将查询字段作为key,前端字段作为value
                    if (putValue) {
                        params.put(kv[0], fv);
                    } else { //返回给前端字段
                        params.put(getFontFiled(fv), "");
                    }

                } else if (putValue) { //这种情况是  xxx = '1'  写死
                    params.put(kv[0], fv);
                }
            }
        }
        return params;
    }

    public static String getFontFiled(String fv) {
        return (fv.indexOf("${") == 0 && fv.lastIndexOf("}") == fv.length() - 1) ? fv.substring(2, fv.length() - 1) : fv;
    }

    public static void doSetId(Map<String, Object> columnAndValueMap, Map<String, String> genIdMap, String dbType) {
        if (MapUtil.isNotEmpty(genIdMap)) {
            for (String key : genIdMap.keySet()) {
                if ("uuid".equals(genIdMap.get(key).toLowerCase())) {
                    if (DbType.SQL_SERVER.getDb().toString().equals(dbType)) {
                        columnAndValueMap.put(key, UUID.randomUUID());
                    } else {
                        columnAndValueMap.put(key, new IdUtil().nextId());
                    }

                } else {
                    throw new RuntimeException("已监控到非法操作！");
                }

            }
        }
    }

    public static Object[] getCount(String tableName, Map<String, Object> where) {
        StringBuilder sql = new StringBuilder();
        sql.append("select count(*) as coun  from ").append(tableName).append(" where ");
        Object[] values = new Object[where.size()];
        int i = 0;
        for (String key : where.keySet()) {
            if (i != 0) {
                sql.append(" and ");
            }
            sql.append(key).append(" = ?");
            values[i] = where.get(key);
            i++;
        }
        return new Object[]{sql.toString(), values};

    }

    public static Object[] getInsertSql2(String tableName, Map<String, Object> columnAndValueMap, Map<String, String> genIdMap, String dbType) {
        StringBuilder sql = new StringBuilder();
        StringBuilder value = new StringBuilder();
        doSetId(columnAndValueMap, genIdMap, dbType);
        sql.append("INSERT INTO ").append(tableName).append(" (");
        Object[] values = new Object[columnAndValueMap.size()];
        int index = 0;
        for (String key : columnAndValueMap.keySet()) {
            if (value.length() != 0) {
                value.append(",");
                sql.append(",");
            }
            sql.append(key);
            value.append(" ? ");
            values[index] = columnAndValueMap.get(key);
            index++;
        }
        sql.append(")VALUES(").append(value).append(")");
        return new Object[]{sql.toString(), values};
    }

    public static Object[] getInsertSql2(String tableName, Map<String, Object> columnAndValueMap, String dbType) {
        return getInsertSql2(tableName, columnAndValueMap, null, dbType);
    }

    public static Object[] getInsertSql2(BatchSaveParameter batchSaveParameter) {
        List<Object[]> list = new ArrayList<>();
        Set<String> keys = null;
        for (Map<String, Object> columnAndValueMap : batchSaveParameter.getColumnAndValueListMap()) {
            doSetId(columnAndValueMap, batchSaveParameter.getGenIdMap(), batchSaveParameter.getDbType());
            if (keys == null) {
                keys = columnAndValueMap.keySet();
            }
            int index = 0;
            Object[] values = new Object[keys.size()];
            for (String key : keys) {
                values[index] = columnAndValueMap.get(key);
                index++;
            }
            list.add(values);
        }

        StringBuilder sql = new StringBuilder();
        StringBuilder value = new StringBuilder();
        sql.append("INSERT INTO ").append(batchSaveParameter.getTableName()).append(" (");
        for (String key : keys) {
            if (value.length() != 0) {
                value.append(",");
                sql.append(",");
            }
            sql.append(key);
            value.append(" ? ");
        }
        sql.append(")VALUES(").append(value).append(")");
        return new Object[]{sql.toString(), list};
    }

    public static String getInsertSql(String tableName, Map<String, Object> columnAndValueMap) {
        StringBuilder sql = new StringBuilder();
        StringBuilder value = new StringBuilder();
        sql.append("INSERT INTO ").append(tableName).append(" (");
        for (String key : columnAndValueMap.keySet()) {
            if (value.length() != 0) {
                value.append(",");
                sql.append(",");
            }
            sql.append(key);
            value.append(" #{columnAndValueMap.").append(key).append("} ");
        }
        sql.append(")VALUES(").append(value).append(")");
        return sql.toString();
    }

    public static String getUpdateSql(String tableName, Map<String, Object> columnAndValueMap, Map<String, Object> whereMap) {
        StringBuilder sql = new StringBuilder();
        boolean first = true;
        sql.append("UPDATE ").append(tableName).append(" SET ");
        for (String key : columnAndValueMap.keySet()) {
            if (!first) {
                sql.append(",");
            } else {
                first = false;
            }
            sql.append(key).append(" = ").append(" #{columnAndValueMap.").append(key).append("} ");
        }
        first = true;
        for (String key : whereMap.keySet()) {
            if (!first) {
                sql.append(" AND ");
            } else {
                first = false;
                sql.append(" WHERE ");
            }
            sql.append(key).append(" = ").append("#{whereMap.").append(key).append("} ");
        }
        return sql.toString();
    }

    public static Object[] getUpdateSql2(String tableName, Map<String, Object> columnAndValueMap, Map<String, Object> whereMap) {
        StringBuilder sql = new StringBuilder();
        boolean first = true;
        sql.append("UPDATE ").append(tableName).append(" SET ");
        Object[] values = new Object[columnAndValueMap.size() + whereMap.size()];
        int index = 0;
        for (String key : columnAndValueMap.keySet()) {
            if (!first) {
                sql.append(",");
            } else {
                first = false;
            }
            sql.append(key).append(" = ").append(" ? ");
            values[index] = columnAndValueMap.get(key);
            index++;
        }
        first = true;
        if (whereMap.size() == 0) {
            throw new RuntimeException("更新条件不能为null");
        }
        for (String key : whereMap.keySet()) {
            if (key.equals(whereMap.get(key))) {
                throw new RuntimeException("已监控到非法操作！");
            }
            if (!first) {
                sql.append(" AND ");
            } else {
                first = false;
                sql.append(" WHERE ");
            }
            sql.append(key).append(" = ? ");
            values[index] = whereMap.get(key);
            index++;
        }
        return new Object[]{sql.toString(), values};
    }

    public static Map<String, Object> getWhere(List<String> tableKey, Map<String, Object> columnAndValueMap) {
        Map<String, Object> where = null;
        if (tableKey == null) {
            return where;
        }
        for (String key : tableKey) {
            if (columnAndValueMap.get(key) != null && isNotEmpty(columnAndValueMap.get(key).toString())) {
                if (where == null) {
                    where = new HashMap<>();
                }
                where.put(key, columnAndValueMap.get(key));
            }
        }
        return where;
    }
}
